// backend/src/services/robot/RobotProxy.js
const WebSocket = require('ws');
const protobufManager = require('../../protocols/protobuf');
const logger = require('../../utils/logger');
const redis = require('../../utils/redis');

class RobotProxy {
    constructor() {
        this.robots = new Map(); // deviceId -> {ws, info, clients}
        this.messageHandlers = new Map();
        this.setupMessageHandlers();
    }

    setupMessageHandlers() {
        // 注册消息处理器
        this.messageHandlers.set('SystemInfoGroup', this.handleSystemInfo.bind(this));
        this.messageHandlers.set('PeriphInfoGroup', this.handlePeriphInfo.bind(this));
        // 添加更多消息处理器...
    }

    async connectToRobot(deviceId, robotAddress) {
        try {
            const ws = new WebSocket(robotAddress);
            ws.binaryType = 'arraybuffer';

            const robotConnection = {
                ws,
                info: {},
                clients: new Set(),
                connected: false
            };

            ws.on('open', () => this.handleRobotConnection(deviceId, robotConnection));
            ws.on('message', (data) => this.handleRobotMessage(deviceId, data));
            ws.on('close', () => this.handleRobotDisconnection(deviceId));
            ws.on('error', (error) => this.handleRobotError(deviceId, error));

            this.robots.set(deviceId, robotConnection);
            return true;
        } catch (error) {
            logger.error(`Failed to connect to robot ${deviceId}:`, error);
            return false;
        }
    }

    async handleRobotConnection(deviceId, robotConnection) {
        try {
            robotConnection.connected = true;
            logger.info(`Connected to robot ${deviceId}`);

            // 初始化查询
            this.queryRobotInfo(deviceId);

            // 通知所有关联的客户端
            this.broadcastToClients(deviceId, {
                type: 'robot_connected',
                deviceId
            });

            // 更新 Redis 缓存
            await redis.set(`robot:${deviceId}:status`, 'connected');
        } catch (error) {
            logger.error(`Error in robot connection handler for ${deviceId}:`, error);
        }
    }

    async handleRobotMessage(deviceId, data) {
        try {
            // 解码消息
            const message = protobufManager.decodeMessage(data);
            if (!message) {
                logger.warn(`Unrecognized message from robot ${deviceId}`);
                return;
            }

            logger.debug(`Received message from robot ${deviceId}:`, message);

            // 处理不同类型的消息
            switch (message.type) {
                case 'SystemInfoGroup':
                    await this.handleSystemInfo(deviceId, message.data);
                    break;
                case 'PeriphInfoGroup':
                    await this.handlePeriphInfo(deviceId, message.data);
                    break;
                // ... 处理其他消息类型
            }

            // 转发到客户端
            this.broadcastToClients(deviceId, {
                type: 'robot_data',
                messageType: message.type,
                data: message.data,
                timestamp: message.timestamp
            });

        } catch (error) {
            logger.error(`Error handling robot message from ${deviceId}:`, error);
        }
    }

    async decodeRobotMessage(data) {
        // 解码通用消息封装
        const RemoteXferMessage = protobufManager.root.lookupType('mstf.camb.proto.RemoteXferMessage');
        const message = RemoteXferMessage.decode(new Uint8Array(data));

        // 根据消息内容确定具体类型并解码
        // TODO: 实现消息类型判断和具体解码逻辑

        return {
            type: 'unknown',
            data: message
        };
    }

    async handleRobotDisconnection(deviceId) {
        const robotConnection = this.robots.get(deviceId);
        if (robotConnection) {
            robotConnection.connected = false;
            robotConnection.clients.forEach(client => {
                client.send(JSON.stringify({
                    type: 'robot_disconnected',
                    deviceId
                }));
            });
        }

        await redis.set(`robot:${deviceId}:status`, 'disconnected');
        logger.info(`Robot ${deviceId} disconnected`);
    }

    handleRobotError(deviceId, error) {
        logger.error(`Robot ${deviceId} connection error:`, error);
    }

    // 客户端订阅机器人数据
    subscribeClient(deviceId, clientWs) {
        const robotConnection = this.robots.get(deviceId);
        if (robotConnection) {
            robotConnection.clients.add(clientWs);
            clientWs.on('close', () => {
                robotConnection.clients.delete(clientWs);
            });
        }
    }

    // 发送命令到机器人
    async sendCommand(deviceId, command) {
        try {
            const robotConnection = this.robots.get(deviceId);
            if (!robotConnection || !robotConnection.connected) {
                throw new Error('Robot not connected');
            }

            // 编码并发送命令
            const buffer = protobufManager.encodeRemoteXferMessage(
                command.type,
                command.data
            );
            robotConnection.ws.send(buffer);

            logger.debug(`Sent command to robot ${deviceId}:`, command);
        } catch (error) {
            logger.error(`Error sending command to robot ${deviceId}:`, error);
            throw error;
        }
	}

    // 查询机器人信息
    queryRobotInfo(deviceId) {
        const robotConnection = this.robots.get(deviceId);
        if (robotConnection && robotConnection.connected) {
            this.sendCommand(deviceId, {
                type: 'SystemInfoGroup',
                data: { query: {} }
            });
            this.sendCommand(deviceId, {
                type: 'PeriphInfoGroup',
                data: { query: {} }
            });
        }
    }

    // 广播消息给所有订阅的客户端
    broadcastToClients(deviceId, message) {
        const robotConnection = this.robots.get(deviceId);
        if (robotConnection) {
            const messageStr = JSON.stringify(message);
            robotConnection.clients.forEach(client => {
                if (client.readyState === WebSocket.OPEN) {
                    client.send(messageStr);
                }
            });
        }
    }

    // 处理具体类型的消息
    async handleSystemInfo(deviceId, data) {
        // 处理系统信息
        await redis.set(`robot:${deviceId}:systemInfo`, JSON.stringify(data));
    }

    async handlePeriphInfo(deviceId, data) {
        // 处理外设信息
        await redis.set(`robot:${deviceId}:periphInfo`, JSON.stringify(data));
    }
}

module.exports = new RobotProxy();
